package org.one.stone.soup.grfxML;

import org.one.stone.soup.mjdb.data.field.DataLinker;
import org.one.stone.soup.mjdb.data.field.Field;
import org.one.stone.soup.mjdb.data.field.IntField;
import org.one.stone.soup.mjdb.data.field.LockException;
import org.one.stone.soup.mjdb.data.field.NullField;
import org.one.stone.soup.xml.XmlElement;
  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

/**
	*
	* @author Nik Cross
*/
public class DataNode extends NullField implements ITag {
	public static String DEFAULT_ID = "_Node";

	private GrfxMLEngine engine;

		DataNode parent;

		DataTranslation translation = new DataTranslation();
		DataBehaviour behaviour = null;
		DataShape shape = new DataShape();
		DataChildren children;
		DataProcess process;
		DataAnchors anchors;
		DataStore data = null;
		DataPoint bounds = new DataPoint();

	String _prototype = null;

	private int zOrder;
	public DataNode(GrfxMLEngine engine) {
		this(engine,null);
	}

public DataNode(GrfxMLEngine engine,DataNode parent) {

	this.parent = parent;
	process = new DataProcess(engine,this);
	anchors = new DataAnchors(engine);
	children = new DataChildren(engine,this);
	this.engine = engine;

	try{
		setId(DEFAULT_ID,this);
	}
	catch(LockException le){} //Dummy catch
}
public void buildFromgrfxML(XmlElement xml)
{

	String name = xml.getAttributeValueByName(Token.ID);
	if(name!=null)
	{
		try{
			setId(name,this);
		}
		catch(LockException le){} //Dummy catch
		String prototypeName = xml.getAttributeValueByName("prototype");
		if(prototypeName!=null)
		{
			GrfxMLPrototypeBuilder.buildPrototype(engine,this,prototypeName,parent);
			_prototype = prototypeName;
			//return; //?
		}
	}

	XmlElement element;

	for(int loop=0;loop<xml.getElementCount();loop++)
	{
		element = xml.getElementByIndex(loop);
		if(element == null)
			continue;

		String eleName = element.getName();

		if(eleName.equals(Token.PROCESS))
		{
			process = new DataProcess(engine,this);
			process.buildFromgrfxML(element);
		}
		else if(eleName.equals(Token.TRANSLATION))
		{
			translation = new DataTranslation();
			translation.buildFromgrfxML(element);
		}
		else if(eleName.equals(Token.BEHAVIOUR))
		{
			behaviour = new DataBehaviour();
	  		behaviour.buildFromgrfxML(element);
		}
		else if(eleName.equals(Token.DATA))
		{
			data = new DataStore(engine);

			if(_prototype==null)
			{
				data.buildFromgrfxML(element);
			}
			else
			{
	  			data.buildFromgrfxML(name,element);
			}
	  	}
		else if(eleName.equals(Token.SHAPE))
		{
			shape = new DataShape();
			shape.buildFromgrfxML(element);
		}
		else if(eleName.equals(Token.CHILDREN))
		{
			children = new DataChildren(engine,this);
			children.buildFromgrfxML(element);
		}
		else if(eleName.equals(Token.ANCHORS))
		{
			anchors = new DataAnchors(engine);
	  		anchors.buildFromgrfxML(element);
		}
		else if( !NameHelper.isSystemName(element.getName()) )
		{
			GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{eleName,Token.NODE,""+xml.getStartLineNo()} );
		}
	}
}
public void copyFromgrfxML(XmlElement xml)
{
	XmlElement element;

	for(int loop=0;loop<xml.getElementCount();loop++)
	{
		element = xml.getElementByIndex(loop);
		if(element == null)
			continue;

		String eleName = element.getName();

		if(eleName.equals(Token.PROCESS))
		{
			process.copyFromgrfxML(element);
		}
		else if(eleName.equals(Token.TRANSLATION))
		{
			translation.copyFromgrfxML(element);
		}
		else if(eleName.equals(Token.BEHAVIOUR))
		{
	  		behaviour.copyFromgrfxML(element);
		}
		else if(eleName.equals(Token.DATA))
		{
			data = new DataStore(engine);

			if(_prototype==null)
			{
				data.copyFromgrfxML(element);
			}
			else
			{
	  			data.copyFromgrfxML(getId(),element);
			}
	  	}
		else if(eleName.equals(Token.SHAPE))
		{
			shape.copyFromgrfxML(element);
		}
		else if(eleName.equals(Token.CHILDREN))
		{
			children.copyFromgrfxML(element);
		}
		else if(eleName.equals(Token.ANCHORS))
		{
	  		anchors.copyFromgrfxML(element);
		}
		else
		{
			GrfxMLException.warning( GrfxMLException.WARNING_UNRECOGNISED_TAG_CODE ,new Object[]{eleName,Token.NODE,""+element.getStartLineNo()} );
		}
	}
}
public DataAnchors getAnchors() {
	return anchors;
}
public DataBehaviour getBehaviour() {

	if(behaviour==null)
	{
		behaviour = new DataBehaviour();
	}

	return behaviour;
}
public DataPoint getBounds() {
	return bounds;
}
public DataChildren getChildren() {
	return children;
}
public DataNode getClone() {
	DataNode newNode = new DataNode(engine,parent);

	newNode.translation = translation.getClone();
	if(behaviour==null)
	{
		newNode.behaviour = null;
	}
	else
	{
		newNode.behaviour = behaviour.getClone();
	}

	newNode.shape = shape.getClone();
	newNode.children = children.getClone();
	newNode.process = process.getClone();
	newNode.anchors = anchors.getClone();

	if(data==null)
	{
		data = new DataStore(engine);
	}
	newNode.data = data.getClone();

	return newNode;
}
public DataNode getClone(String path) {

	DataNode newNode = new DataNode(engine,parent);

	GrfxMLStoreProcessor.setCloneName( path,this,newNode );

	if(_prototype!=null)
	{
		newNode._prototype = _prototype;
		GrfxMLPrototypeBuilder.buildPrototype(engine,newNode,_prototype,parent);
		//return newNode; //?
	}

	newNode.translation = translation.getClone(path);
	if(behaviour==null)
	{
		newNode.behaviour = null;
	}
	else
	{
		newNode.behaviour = behaviour.getClone(path);
	}

	newNode.shape = shape.getClone(path);
	newNode.children = children.getClone(path);
	newNode.process = process.getClone(path);
	newNode.process.setParent( newNode );
	newNode.anchors = anchors.getClone(path);
	if(data==null)
	{
		data=new DataStore(engine);
	}
	newNode.data = data.getClone(path);

	return newNode;
}
public DataStore getData() {
	if(data==null)
		data=new DataStore(engine);
	return data;
}
public DataProcess getProcess() {
	return process;
}
/**
 *
 * @return java.lang.String
 */
public String getPrototypeName() {
	return _prototype;
}
public DataShape getShape() {
	return shape;
}
public DataTranslation getTranslation() {
	return translation;
}

public int getZOrder() {
	return zOrder;
}

public void setZOrder(int z) {
	zOrder = z;
}

public void register(DataLinker store) {

	try{
		store.add(process,this);
	}
	catch(LockException le)
	{}//Dummy catch
	process.register(store);

	try{
		store.add(translation,this);
	}
	catch(LockException le)
	{}//Dummy catch
	translation.register(store);

	if(behaviour!=null)
	{
		try{
			store.add(behaviour,this);
		}
		catch(LockException le)
		{}//Dummy catch
		behaviour.register(store);
	}

	try{
		store.add(shape,this);
	}
	catch(LockException le)
	{}//Dummy catch
	shape.register(store);

	try{
		store.add(children,this);
	}
	catch(LockException le)
	{}//Dummy catch
	children.register(store);

	try{
		store.add(anchors,this);
	}
	catch(LockException le)
	{}//Dummy catch
	anchors.register(store);

	if(data!=null)
	{
		try{
			store.add(data,this);
		}
		catch(LockException le)
		{}//Dummy catch
		data.register(store);
	}
}
public void replace(Field oldObj, Field newObj) {
	replace(oldObj, newObj, false);
}
public void replace(Field oldObj, Field newObj,boolean recursive) {

	if(oldObj==parent)
	{
		parent = (DataNode)newObj;
	}

	if(translation==oldObj)
		translation=(DataTranslation)newObj;

	if(behaviour!=null && behaviour==oldObj)
	{
		behaviour=(DataBehaviour)newObj;
		return;
	}

	if(data==oldObj)
		data=(DataStore)newObj;

	if(shape==oldObj)
		shape=(DataShape)newObj;

	if(children==oldObj)
		children=(DataChildren)newObj;

	if(process==oldObj)
		process=(DataProcess)newObj;

	if(anchors==oldObj)
		anchors=(DataAnchors)newObj;

	if(recursive)
	{
		translation.replace(oldObj,newObj,recursive);

		if(behaviour!=null)
		{
			behaviour.replace(oldObj,newObj,recursive);
		}

		if(data!=null)
		{
			data.replace(oldObj,newObj,recursive);
		}

		shape.replace(oldObj,newObj,recursive);

		children.replace(oldObj,newObj,recursive);

		process.replace(oldObj,newObj,recursive);

		anchors.replace(oldObj,newObj,recursive);
	}

}
public void resetChanged() {

	//translation.resetChanged();
	if (behaviour != null) {
		behaviour.resetChanged();
	}
	if (data != null) {
		data.resetChanged();
	}
	shape.resetChanged();
	children.resetChanged();
	process.resetChanged();
	anchors.resetChanged();
	translation.resetChanged();
}

public void setParent(DataNode newParent) {
	parent = newParent;

	children.setParent( this );
}

protected void setAnchors(DataAnchors newAnchors) {
	anchors = newAnchors;
}
protected void setBehaviour(DataBehaviour newBehaviour) {
	behaviour = newBehaviour;
}
/**
 *
 * @param newChildren org.one.stone.soup.grfxML.DataChildren
 */
protected void setChildren(DataChildren newChildren) {
	children = newChildren;
}

public void setData(DataStore newData) {
	data = newData;
}
/**
 *
 * @param newProcess org.one.stone.soup.grfxML.DataProcess
 */
protected void setProcess(DataProcess newProcess) {
	process = newProcess;
}
/**
 *
 * @param newShape org.one.stone.soup.grfxML.DataShape
 */
protected void setShape(DataShape newShape) {
	shape = newShape;
}
/**
 *
 * @param newTranslation org.one.stone.soup.grfxML.DataTranslation
 */
protected void setTranslation(DataTranslation newTranslation) {
	translation = newTranslation;
}

public String togrfxML(String name) {
	String xml = null;
	if (_prototype != null) {
		xml = "<" + name + " id=\"" + getId() + "\" prototype=\"" + _prototype + "\">";
		if (data != null) {
			xml += data.togrfxML("data");
		}
		xml += "</" + name + ">\n";
		return xml;
	}
	if (NameHelper.isSystemName(getId())) {
		xml = "<" + name + ">";
	} else {
		xml = "<" + name + " id=\"" + getId() + "\">";
	}
	xml += translation.togrfxML(Token.TRANSLATION);
	if (behaviour != null) {
		xml += behaviour.togrfxML(Token.BEHAVIOUR);
	}
	if (data != null) {
		xml += data.togrfxML(Token.DATA);
	}
	xml += shape.togrfxML(Token.SHAPE);
	xml += children.togrfxML(Token.CHILDREN);
	xml += process.togrfxML(Token.PROCESS);
	xml += anchors.togrfxML(Token.ANCHORS);
	xml += "</" + name + ">\n";
	return xml;
}
public String togrfxML(String name,TagModifier modifier) {
	return togrfxML(name);
}
public String toString()
{
	if(GrfxMLEngine.DEBUG)
		return(togrfxML( DEFAULT_ID.substring(1) ));

	String xml = "<"+DEFAULT_ID.substring(1).toLowerCase();

	if(!NameHelper.isSystemName(getId()))
	{
		xml += " id=\""+getId()+"\"";
	}

	xml+="/>";

	return xml;
}
public void translate(DataTranslation t) {

	// translate this node
	translation.translate(t);

	shape.translate(translation);

//	GrfxMLProcessor.process(engine,engine.getAPI(),this,t); // Makes heirachy work

	// translate the child nodes
	children.translate(translation);

	GrfxMLProcessor.process(engine,engine.getAPI(),this,t); //Makes select work


	if(translation.getVisible().getValue()==true)
	{
		DataPoint check;
		int w;
		int mw=IntField.INT_MAX_NEG;
		int h;
		int mh=IntField.INT_MAX_NEG;

		try {
			check = children.getBounds();
			w = check.getValueX();
			h = check.getValueY();
			if(w>mw)
				mw=w;
			if(h>mh)
				mh=h;

			check = shape.getBounds();
			w = check.getValueX();
			h = check.getValueY();
			if(w>mw)
				mw=w;
			if(h>mh)
				mh=h;
		} catch (Exception e) {} //dummy catch

		try{
			bounds.setValueX(mw,this);
			bounds.setValueY(mh,this);
		}
		catch(LockException le){}//dummy catch
	}
	else
	{
		try{
			bounds.setValueX(0,this);
			bounds.setValueY(0,this);
		}
		catch(LockException le){}//dummy catch
	}
}

public DataNode getParent()
{
	return parent;
}
}
